package cn.virens;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

import org.tio.core.ChannelContext;
import org.tio.core.Tio;

import cn.virens.packet.WritePacket;

public class TioUtil {

	/**
	 * 设备版本
	 * 
	 * @param  channelContext
	 * @return
	 */
	public static String ver(ChannelContext channelContext) {
		return String.valueOf(channelContext.getAttribute("var"));
	}

	/**
	 * 设备IMEI地址
	 * 
	 * @param  channelContext
	 * @return
	 */
	public static String imei(ChannelContext channelContext) {
		return channelContext.getBsId();
	}

	/**
	 * 连接名称
	 * 
	 * @param  channelContext
	 * @return
	 */
	public static String name(ChannelContext channelContext) {
		return channelContext + "[" + imei(channelContext) + "]";
	}

	/**
	 * 心跳空闲计数
	 * 
	 * @param  channelContext
	 * @param  function
	 * @return
	 */
	public static <R> R heartIdle(ChannelContext channelContext, Function<AtomicInteger, R> function) {
		Object temp = channelContext.getAttribute("_heartIdle");

		AtomicInteger idleCount = null;
		try {
			if (temp instanceof AtomicInteger) {
				idleCount = (AtomicInteger) temp;
			} else {
				idleCount = new AtomicInteger(0);
			}

			return function.apply(idleCount);
		} finally {
			channelContext.setAttribute("_heartIdle", idleCount);
		}
	}

	/**
	 * 心跳计数
	 * 
	 * @param  channelContext
	 * @param  function
	 * @return
	 */
	public static <R> R heartTimes(ChannelContext channelContext, Function<AtomicInteger, R> function) {
		Object temp = channelContext.getAttribute("_heartTimes");

		AtomicInteger heartbeatCount = null;
		try {
			if (temp instanceof AtomicInteger) {
				heartbeatCount = (AtomicInteger) temp;
			} else {
				heartbeatCount = new AtomicInteger(0);
			}

			return function.apply(heartbeatCount);
		} finally {
			channelContext.setAttribute("_heartTimes", heartbeatCount);
		}
	}

	public static <T> T getAttribute(ChannelContext context, String key, Class<T> clazz) {
		return getAttribute(context, key, clazz, null);
	}

	@SuppressWarnings("unchecked")
	public static <T> T getAttribute(ChannelContext context, String key, Class<T> clazz, T defValue) {
		Object answer = context.getAttribute(key);

		if (answer != null && clazz.isAssignableFrom(answer.getClass())) {
			return (T) answer;
		} else {
			return defValue;
		}
	}

	/**
	 * 生成新的发送包
	 * 
	 * @param  channelContext
	 * @return
	 */
	public static WritePacket write(ChannelContext channelContext) {
		Object temp = channelContext.getAttribute("_sendTimers");

		AtomicInteger sendTimer = null;
		try {
			if (temp instanceof AtomicInteger) {
				sendTimer = (AtomicInteger) temp;
			} else {
				sendTimer = new AtomicInteger(0);
			}

			// 构建待发送包
			WritePacket writePacket = new WritePacket();
			writePacket.seq(sendTimer.incrementAndGet());
			writePacket.ver(ver(channelContext));

			return writePacket;
		} finally {
			channelContext.setAttribute("_sendTimers", sendTimer);
		}
	}

	/**
	 * 发送指令通道
	 * 
	 * @param  channelContext 设备连接
	 * @param  packet         数据包
	 * @return
	 */
	public static boolean write(ChannelContext channelContext, WritePacket packet) {
		return Tio.send(channelContext, packet);
	}
}
